<template>
  <div class="in-editor-wrapper">
    <el-upload
      :action="uploadUrl"
      :before-upload="handleBeforeUpload"
      :on-success="handleUploadSuccess"
      :on-error="handleUploadError"
      name="file"
      :show-file-list="false"
      :headers="headers"
      style="display: none"
      ref="upload"
      v-if="this.type == 'url'"
    >
    </el-upload>
    <div class="editor in-editor ql-editor" ref="editor" :style="styles"></div>
  </div>
</template>

<script>
import Quill from "quill";
import "quill/dist/quill.core.css";
import "quill/dist/quill.snow.css";
import "quill/dist/quill.bubble.css";
import { getToken } from "@/utils/auth";
import axios from "axios";
import QuillBetterTable from "quill-better-table";
import "quill-better-table/dist/quill-better-table.css";
const titleConfig = {
  "ql-bold": "加粗",
  "ql-color": "颜色",
  "ql-font": "字体",
  "ql-code": "插入代码",
  "ql-italic": "斜体",
  "ql-link": "添加链接",
  "ql-background": "颜色",
  "ql-size": "字体大小",
  "ql-strike": "删除线",
  "ql-script": "上标/下标",
  "ql-underline": "下划线",
  "ql-blockquote": "引用",
  "ql-header": "标题",
  "ql-indent": "缩进",
  "ql-list": "列表",
  "ql-align": "文本对齐",
  "ql-direction": "文本方向",
  "ql-code-block": "代码块",
  "ql-formula": "公式",
  "ql-image": "图片",
  "ql-video": "视频",
  "ql-clean": "清除字体样式",
  "ql-upload": "文件",
  "ql-table": "插入表格",
  "ql-table-insert-row": "插入行",
  "ql-table-insert-column": "插入列",
  "ql-table-delete-row": "删除行",
  "ql-table-delete-column": "删除列",
};
Quill.register(
  {
    "modules/better-table": QuillBetterTable,
  },
  true
);

export default {
  name: "Editor",
  props: {
    flag: {
      type: Boolean,
      default: true,
    },
    /* 编辑器的内容 */
    value: {
      type: String,
      default: "",
    },
    /* 高度 */
    height: {
      type: Number,
      default: null,
    },
    /* 最小高度 */
    minHeight: {
      type: Number,
      default: 480,
    },
    /* 只读 */
    readOnly: {
      type: Boolean,
      default: false,
    },
    // 上传文件大小限制(MB)
    fileSize: {
      type: Number,
      default: 5,
    },
    /* 类型（base64格式、url格式） */
    type: {
      type: String,
      default: "url",
    },
  },
  data() {
    return {
      urls: [],
      uploadUrl: process.env.VUE_APP_BASE_API + "/common/upload", // 上传的图片服务器地址
      headers: {
        Authorization: "Bearer " + getToken(),
      },
      Quill: null,
      currentValue: "",
      // options: {
      //   theme: 'snow',
      //   bounds: document.body,
      //   debug: 'warn',
      //   modules: {
      //     // 工具栏配置
      //     toolbar: [
      //       ['bold', 'italic', 'underline', 'strike'], // 加粗 斜体 下划线 删除线
      //       ['blockquote', 'code-block'], // 引用  代码块
      //       [{ list: 'ordered' }, { list: 'bullet' }], // 有序、无序列表
      //       [{ indent: '-1' }, { indent: '+1' }], // 缩进
      //       [{ size: ['small', false, 'large', 'huge'] }], // 字体大小
      //       [{ header: [1, 2, 3, 4, 5, 6, false] }], // 标题
      //       [{ color: [] }, { background: [] }], // 字体颜色、字体背景颜色
      //       [{ align: [] }], // 对齐方式
      //       ['clean'] // 清除文本格式
      //       // ['link', 'image', 'video'] // 链接、图片、视频
      //     ]
      //   },
      //   placeholder: '请输入内容',
      //   readOnly: this.readOnly
      // }
      // options: {
      //   theme: 'snow',
      //   modules: {
      //     toolbar: {
      //       container: [
      //         ['bold', 'italic', 'underline', 'strike'],
      //         [{ header: 1 }, { header: 2 }],
      //         [{ list: 'ordered' }, { list: 'bullet' }],
      //         [{ indent: '-1' }, { indent: '+1' }],
      //         [{ color: [] }, { background: [] }],
      //         [{ font: [] }],
      //         [{ align: [] }],
      //         ['clean'],
      //         [
      //           { table: 'TD' },
      //           { 'table-insert-row': 'TIR' },
      //           { 'table-insert-column': 'TIC' },
      //           { 'table-delete-row': 'TDR' },
      //           { 'table-delete-column': 'TDC' }
      //         ]
      //       ],
      //       handlers: {
      //         table: function (val) {
      //           this.quill.getModule('table').insertTable(2, 3)
      //         },
      //         'table-insert-row': function () {
      //           this.quill.getModule('table').insertRowBelow()
      //         },
      //         'table-insert-column': function () {
      //           this.quill.getModule('table').insertColumnRight()
      //         },
      //         'table-delete-row': function () {
      //           this.quill.getModule('table').deleteRow()
      //         },
      //         'table-delete-column': function () {
      //           this.quill.getModule('table').deleteColumn()
      //         }
      //       }
      //     },
      //     table: true
      //   },
      //   placeholder: ''
      // }
      options: {
        theme: "snow",
        bounds: document.body,
        debug: "warn",
        modules: {
          // 工具栏的具体配置
          toolbar: {
            container: [
              ["bold", "italic", "underline", "strike"],
              ["blockquote", "code-block"],
              [{ list: "ordered" }, { list: "bullet" }],
              [{ script: "super" }],
              [{ indent: "-1" }, { indent: "+1" }],
              [{ size: ["small", false, "large", "huge"] }],
              [{ header: [1, 2, 3, 4, 5, 6, false] }],
              [{ color: [] }, { background: [] }],
              [{ align: [] }],
              ["clean"], // 清除文本格式
              ["link", "image", "video"], // 链接、图片、视频
              [{ table: "TD" }],
            ],
            handlers: {
              table: function () {
                // 默认插入的表格行列数
                this.quill.getModule("better-table").insertTable(5, 5);
              },
            },
          },
          table: false,
          "better-table": {
            operationMenu: {
              items: {
                // unmergeCells: {
                //   text: 'Another unmerge cells name'
                // },
                insertColumnRight: {
                  text: "右边插入一列",
                },
                insertColumnLeft: {
                  text: "左边插入一列",
                },
                insertRowUp: {
                  text: "上边插入一行",
                },
                insertRowDown: {
                  text: "下边插入一行",
                },
                mergeCells: {
                  text: "合并单元格",
                },
                unmergeCells: {
                  text: "拆分单元格",
                },
                deleteColumn: {
                  text: "删除列",
                },
                deleteRow: {
                  text: "删除行",
                },
                deleteTable: {
                  text: "删除表格",
                },
              },
              background: {
                color: "#333",
              },
              color: {
                colors: ["green", "red", "yellow", "blue", "white"],
                text: "background:",
              },
            },
          },
          keyboard: {
            bindings: QuillBetterTable.keyboardBindings,
          },
        },
        placeholder: "请输入内容 ...",
        readOnly: this.readOnly,
      },
    };
  },
  computed: {
    styles() {
      let style = {};
      if (this.minHeight) {
        style.minHeight = `${this.minHeight}px`;
      }
      if (this.height) {
        style.height = `${this.height}px`;
      }
      return style;
    },
  },
  watch: {
    value: {
      handler(val) {
        if (val !== this.currentValue) {
          this.currentValue = val === null ? "" : val;
          if (this.Quill) {
            this.Quill.clipboard.dangerouslyPasteHTML(this.currentValue);
          }
        }
      },
      immediate: true,
    },
    flag: {
      handler(val) {
        this.Quill.root.contentEditable = val;
      },
    },
  },
  mounted() {
    this.init();
    // 初始化编辑器
    // this._initEditor();
    // this.$el.querySelector(
    //   '.ql-table-insert-row'
    // ).innerHTML = '<svg t="1591862376726" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6306" width="18" height="200"><path d="M500.8 604.779L267.307 371.392l-45.227 45.27 278.741 278.613L779.307 416.66l-45.248-45.248z" p-id="6307"></path></svg>'
    // this.$el.querySelector(
    //   '.ql-table-insert-column'
    // ).innerHTML = '<svg t="1591862238963" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6509" width="18" height="200"><path d="M593.450667 512.128L360.064 278.613333l45.290667-45.226666 278.613333 278.762666L405.333333 790.613333l-45.226666-45.269333z" p-id="6510"></path></svg>'
    // this.$el.querySelector(
    //   '.ql-table-delete-row'
    // ).innerHTML = '<svg t="1591862253524" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6632" width="18" height="200"><path d="M500.8 461.909333L267.306667 695.296l-45.226667-45.269333 278.741333-278.613334L779.306667 650.026667l-45.248 45.226666z" p-id="6633"></path></svg>'
    // this.$el.querySelector(
    //   '.ql-table-delete-column'
    // ).innerHTML = '<svg t="1591862261059" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6755" width="18" height="200"><path d="M641.28 278.613333l-45.226667-45.226666-278.634666 278.762666 278.613333 278.485334 45.248-45.269334-233.365333-233.237333z" p-id="6756"></path></svg>'
    // this.addQuillTitle()
  },
  beforeDestroy() {
    this.Quill = null;
  },
  methods: {
    // // 初始化编辑器
    // _initEditor () {
    //   // 获取编辑器的DOM容器
    //   let editorDom = this.$el.querySelector('.in-editor');

    //   // 初始化编辑器
    //   this.editor = new Quill(editorDom, this.options);

    //   // 双向绑定
    //   this.editor.on('text-change', () => {
    //     this.$emit('input', this.editor.root.innerHTML);
    //   });
    // },
    addQuillTitle() {
      const oToolBar = document.querySelector(".ql-toolbar");
      const aButton = oToolBar.querySelectorAll("button");
      const aSelect = oToolBar.querySelectorAll("select");
      aButton.forEach(function (item) {
        if (item.className === "ql-script") {
          item.value === "sub" ? (item.title = "下标") : (item.title = "上标");
        } else if (item.className === "ql-indent") {
          item.value === "+1"
            ? (item.title = "向右缩进")
            : (item.title = "向左缩进");
        } else {
          item.title = titleConfig[item.classList[0]];
        }
      });
      aSelect.forEach(function (item) {
        item.parentNode.title = titleConfig[item.classList[0]];
      });
    },
    getContentData() {
      return this.Quill.getContents();
    },
    init() {
      const editor = this.$refs.editor;
      this.Quill = new Quill(editor, this.options);
      this.Quill.root.contentEditable = this.flag;
      window.addEventListener(
        "paste",
        (evt) => {
          if (
            evt.clipboardData &&
            evt.clipboardData.files &&
            evt.clipboardData.files.length
          ) {
            evt.preventDefault();
            [].forEach.call(evt.clipboardData.files, (file) => {
              if (!file.type.match(/^image\/(gif|jpe?g|a?png|bmp)/i)) {
                return;
              }
              const formData = new FormData();
              formData.append("file", file);
              axios
                .post(
                  `${process.env.VUE_APP_BASE_API}/common/upload`,
                  formData,
                  {
                    headers: this.headers,
                  }
                )
                .then((res) => {
                  console.log(res);
                  if (res.data.code == 200) {
                    console.log(res.data.data.src);
                    let length = this.Quill.getSelection().index; // 光标位置
                    // 插入图片地址
                    this.Quill.insertEmbed(length, "image", res.data.data.url);
                    // 光标后移一位
                    this.Quill.setSelection(length + 1);
                    this.urls.push(...this.urls, res.data.data.url);
                    const arr = Array.from(new Set(this.urls));
                    this.$emit("getUrls", arr);
                  } else {
                    this.$message({
                      message: res.data.message,
                      type: "warning",
                    });
                  }
                });
            });
          }
        },
        false
      );
      // 如果设置了上传地址则自定义图片上传事件
      if (this.type == "url") {
        let toolbar = this.Quill.getModule("toolbar");
        toolbar.addHandler("image", (value) => {
          this.uploadType = "image";
          if (value) {
            this.$refs.upload.$children[0].$refs.input.click();
          } else {
            this.quill.format("image", false);
          }
        });
      }
      this.Quill.clipboard.dangerouslyPasteHTML(this.currentValue);
      this.Quill.on("text-change", (delta, oldDelta, source) => {
        const html = this.$refs.editor.children[0].innerHTML;
        const text = this.Quill.getText();
        const quill = this.Quill;
        this.currentValue = html;
        this.$emit("input", html);
        this.$emit("on-change", { html, text, quill });
      });
      this.Quill.on("text-change", (delta, oldDelta, source) => {
        this.$emit("on-text-change", delta, oldDelta, source);
      });
      this.Quill.on("selection-change", (range, oldRange, source) => {
        this.$emit("on-selection-change", range, oldRange, source);
      });
      this.Quill.on("editor-change", (eventName, ...args) => {
        this.$emit("on-editor-change", eventName, ...args);
      });
    },
    // 上传前校检格式和大小
    handleBeforeUpload(file) {
      // 校检文件大小
      if (this.fileSize) {
        const isLt = file.size / 1024 / 1024 < this.fileSize;
        if (!isLt) {
          this.$message.error(`上传文件大小不能超过 ${this.fileSize} MB!`);
          return false;
        }
      }
      return true;
    },
    handleUploadSuccess(res, file) {
      // 获取富文本组件实例
      let quill = this.Quill;
      // 如果上传成功
      if (res.code == 200) {
        // 获取光标所在位置
        let length = quill.getSelection().index;
        // 插入图片  res.url为服务器返回的图片地址
        quill.insertEmbed(
          length,
          "image",
          process.env.VUE_APP_BASE_API + res.fileName
        );
        // 调整光标到最后
        quill.setSelection(length + 1);
      } else {
        this.$message.error("图片插入失败");
      }
    },
    handleUploadError() {
      this.$message.error("图片插入失败");
    },
  },
};
</script>

<style lang="scss" scope>
.in-editor-wrapper {
  flex-grow: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  .ql-toolbar {
    .ql-formats {
      .ql-picker-label {
        &::before {
          position: relative;
          top: -5px;
        }
      }
      button {
        i.icon {
          font-size: 14px;
        }
      }
    }
  }
  .ql-container {
    flex-grow: 1;
    height: 0;
    overflow: hidden;
  }
  .quill-better-table-wrapper {
    overflow-x: visible;
  }
  // .qlbt-col-tool {
  //   display: none;
  // }
}
.qlbt-col-tool {
  width: auto !important;
}
.qlbt-operation-menu {
  background-color: #fff;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  font-size: 14px;
  z-index: 10000;
  overflow: hidden;
}
.editor,
.ql-toolbar {
  white-space: pre-wrap !important;
  line-height: normal !important;
}
.quill-img {
  display: none;
}
.ql-snow .ql-tooltip[data-mode="link"]::before {
  content: "请输入链接地址:";
}
.ql-snow .ql-tooltip.ql-editing a.ql-action::after {
  border-right: 0px;
  content: "保存";
  padding-right: 0px;
}

.ql-snow .ql-tooltip[data-mode="video"]::before {
  content: "请输入视频地址:";
}

.ql-snow .ql-picker.ql-size .ql-picker-label::before,
.ql-snow .ql-picker.ql-size .ql-picker-item::before {
  content: "14px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="small"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="small"]::before {
  content: "10px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="large"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="large"]::before {
  content: "18px";
}
.ql-snow .ql-picker.ql-size .ql-picker-label[data-value="huge"]::before,
.ql-snow .ql-picker.ql-size .ql-picker-item[data-value="huge"]::before {
  content: "32px";
}

.ql-snow .ql-picker.ql-header .ql-picker-label::before,
.ql-snow .ql-picker.ql-header .ql-picker-item::before {
  content: "文本";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="1"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="1"]::before {
  content: "标题1";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="2"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="2"]::before {
  content: "标题2";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="3"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="3"]::before {
  content: "标题3";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="4"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="4"]::before {
  content: "标题4";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="5"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="5"]::before {
  content: "标题5";
}
.ql-snow .ql-picker.ql-header .ql-picker-label[data-value="6"]::before,
.ql-snow .ql-picker.ql-header .ql-picker-item[data-value="6"]::before {
  content: "标题6";
}

.ql-snow .ql-picker.ql-font .ql-picker-label::before,
.ql-snow .ql-picker.ql-font .ql-picker-item::before {
  content: "标准字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="serif"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="serif"]::before {
  content: "衬线字体";
}
.ql-snow .ql-picker.ql-font .ql-picker-label[data-value="monospace"]::before,
.ql-snow .ql-picker.ql-font .ql-picker-item[data-value="monospace"]::before {
  content: "等宽字体";
}
.ql-indent-1 {
  padding-left: 0px !important;
  text-indent: 1em !important;
}

.ql-indent-2 {
  padding-left: 0px !important;
  text-indent: 2em !important;
}

.ql-indent-3 {
  padding-left: 0px !important;
  text-indent: 3em !important;
}

.ql-indent-4 {
  padding-left: 0px !important;
  text-indent: 4em !important;
}

.ql-indent-5 {
  padding-left: 0px !important;
  text-indent: 5em !important;
}

.ql-indent-6 {
  padding-left: 0px !important;
  text-indent: 6em !important;
}

.ql-indent-7 {
  padding-left: 0px !important;
  text-indent: 7em !important;
}

.ql-indent-8 {
  padding-left: 0px !important;
  text-indent: 8em !important;
}
</style>
